home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH13 / SRC / OBJCYLR2.CLS < prev    next >
Encoding:
Text File  |  1996-04-12  |  13.5 KB  |  502 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "ObjCylinder"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. ' Point1 and Point2 are points at each end of the
  11. ' cylinder's axis.
  12. Private Point1 As Point3D
  13. Private Point2 As Point3D
  14. Private Radius As Single
  15.  
  16. ' The axis.
  17. Private Ax As Single
  18. Private Ay As Single
  19. Private Az As Single
  20.  
  21. ' The radii vectors.
  22. Private V1x As Single
  23. Private V1y As Single
  24. Private V1z As Single
  25. Private V2x As Single
  26. Private V2y As Single
  27. Private V2z As Single
  28.  
  29. Private HitX As Single
  30. Private HitY As Single
  31. Private HitZ As Single
  32. Private HitT As Single
  33.  
  34. Private Kar As Single
  35. Private Kag As Single
  36. Private Kab As Single
  37.  
  38. Private Kdr As Single
  39. Private Kdg As Single
  40. Private Kdb As Single
  41.  
  42. Private SpecN As Single
  43. Private Ks As Single
  44.  
  45. Private Krr As Single
  46. Private Krg As Single
  47. Private Krb As Single
  48.  
  49. Private Nt As Single
  50. Private N1 As Single   ' Index of refraction outside the object.
  51. Private N2 As Single   ' Index of refraction inside the object.
  52. Private Ktr As Single
  53. Private Ktg As Single
  54. Private Ktb As Single
  55.  
  56. Private IsReflective As Boolean
  57. Private IsTransparent As Boolean
  58.  
  59. ' ************************************************
  60. ' Set constants for transmitted light.
  61. ' ************************************************
  62. Sub SetKt(n As Single, n_1 As Single, n_2 As Single, R As Single, G As Single, B As Single)
  63.     Nt = n
  64.     N1 = n_1
  65.     N2 = n_2
  66.     Ktr = R
  67.     Ktg = G
  68.     Ktb = B
  69.     IsTransparent = (R > 0 Or G > 0 Or B > 0)
  70. End Sub
  71.  
  72. ' ************************************************
  73. ' Initialize N1 and N2 to default values.
  74. ' ************************************************
  75. Private Sub Class_Initialize()
  76.     N1 = 1
  77.     N2 = 1
  78. End Sub
  79.  
  80. ' ************************************************
  81. ' Apply a transformation matrix to the plane.
  82. ' ************************************************
  83. Public Sub Apply(M() As Single)
  84.     ' Transform the points.
  85.     m3Apply Point1.coord, M, Point1.trans
  86.     m3Apply Point2.coord, M, Point2.trans
  87. End Sub
  88.  
  89. ' ************************************************
  90. ' Return the red, green, and blue components of
  91. ' the surface at the hit position.
  92. ' ************************************************
  93. Public Sub HitColor(depth As Integer, Objects As Collection, R As Integer, G As Integer, B As Integer)
  94. Dim Vx As Single
  95. Dim Vy As Single
  96. Dim Vz As Single
  97. Dim nx As Single
  98. Dim ny As Single
  99. Dim nz As Single
  100. Dim lx As Single
  101. Dim ly As Single
  102. Dim lz As Single
  103. Dim rx As Single
  104. Dim ry As Single
  105. Dim rz As Single
  106. Dim n_len As Single
  107. Dim l_len As Single
  108. Dim v_len As Single
  109. Dim r_len As Single
  110. Dim NdotL As Single
  111. Dim RdotV As Single
  112. Dim NdotV As Single
  113. Dim r_dif As Single
  114. Dim g_dif As Single
  115. Dim b_dif As Single
  116. Dim r_amb As Single
  117. Dim g_amb As Single
  118. Dim b_amb As Single
  119. Dim spec As Single
  120. Dim r_ref As Single
  121. Dim g_ref As Single
  122. Dim b_ref As Single
  123. Dim r1 As Integer
  124. Dim g1 As Integer
  125. Dim b1 As Integer
  126. Dim mx As Single
  127. Dim my As Single
  128. Dim mz As Single
  129. Dim LdotV As Single
  130. Dim r_trd As Single
  131. Dim g_trd As Single
  132. Dim b_trd As Single
  133. Dim r_tra As Single
  134. Dim g_tra As Single
  135. Dim b_tra As Single
  136. Dim tx As Single
  137. Dim ty As Single
  138. Dim tz As Single
  139. Dim n_ratio As Single
  140. Dim cos2 As Single
  141. Dim cos1 As Single
  142. Dim cos_factor As Single
  143. Dim NdotT As Single
  144. Dim NdotT_Nt As Single
  145. Dim hit_x As Single
  146. Dim hit_y As Single
  147. Dim hit_z As Single
  148. Dim i As Integer
  149. Dim dist As Single
  150. Dim shadowed As Boolean
  151. Dim rlng As Long
  152. Dim glng As Long
  153. Dim blng As Long
  154.  
  155.     hit_x = HitX
  156.     hit_y = HitY
  157.     hit_z = HitZ
  158.  
  159.     ' *******************************
  160.     ' * Compute local contributions *
  161.     ' *******************************
  162.     
  163.     ' Find the unit vector pointing toward the light.
  164.     lx = LightSource.trans(1) - HitX
  165.     ly = LightSource.trans(2) - HitY
  166.     lz = LightSource.trans(3) - HitZ
  167.     l_len = Sqr(lx * lx + ly * ly + lz * lz)
  168.     lx = lx / l_len
  169.     ly = ly / l_len
  170.     lz = lz / l_len
  171.     ' We will use l_len later as the distance from
  172.     ' the light to the surface.
  173.  
  174.     ' Find the surface unit normal.
  175.     Vx = Point2.trans(1) - Point1.trans(1)
  176.     Vy = Point2.trans(2) - Point1.trans(2)
  177.     Vz = Point2.trans(3) - Point1.trans(3)
  178.     nx = HitX - (Point1.trans(1) + HitT * Vx)
  179.     ny = HitY - (Point1.trans(2) + HitT * Vy)
  180.     nz = HitZ - (Point1.trans(3) + HitT * Vz)
  181.     n_len = Sqr(nx * nx + ny * ny + nz * nz)
  182.     nx = nx / n_len
  183.     ny = ny / n_len
  184.     nz = nz / n_len
  185.     
  186.     ' Find the vector V from the surface to the
  187.     ' viewpoint.
  188.     Vx = EyeX - HitX
  189.     Vy = EyeY - HitY
  190.     Vz = EyeZ - HitZ
  191.     v_len = Sqr(Vx * Vx + Vy * Vy + Vz * Vz)
  192.     Vx = Vx / v_len
  193.     Vy = Vy / v_len
  194.     Vz = Vz / v_len
  195.  
  196.     ' See if the light shines directly on the surface.
  197.     For i = 1 To Objects.Count
  198.         dist = Objects.Item(i).RayDistance( _
  199.             LightSource.trans(1), _
  200.             LightSource.trans(2), _
  201.             LightSource.trans(3), _
  202.             -lx, -ly, -lz)
  203.         If dist < l_len - 0.1 Then Exit For
  204.     Next i
  205.     shadowed = (i <= Objects.Count)
  206.  
  207.     ' Calculate the part due to diffuse reflection.
  208.     If shadowed Then
  209.         ' The light does not hit the surface.
  210.         r_dif = 0
  211.         g_dif = 0
  212.         b_dif = 0
  213.         spec = 0
  214.     Else
  215.         ' Treat backface planes as normal planes.
  216.         NdotL = Abs(nx * lx + ny * ly + nz * lz)
  217.         
  218.         r_dif = Kdr * NdotL
  219.         g_dif = Kdg * NdotL
  220.         b_dif = Kdb * NdotL
  221.         
  222.         ' Find vector R in the mirror direction.
  223.         rx = 2 * nx * NdotL - lx
  224.         ry = 2 * ny * NdotL - ly
  225.         rz = 2 * nz * NdotL - lz
  226.         
  227.         ' Calculate the part due to specular reflection.
  228.         RdotV = rx * Vx + ry * Vy + rz * Vz
  229.         If RdotV < 0 Then
  230.             spec = 0
  231.         Else
  232.             spec = Ks * RdotV ^ SpecN
  233.         End If
  234.     End If
  235.     
  236.     ' Calculate the part due to ambient light.
  237.     r_amb = LightIar * Kar
  238.     g_amb = LightIag * Kag
  239.     b_amb = LightIab * Kab
  240.     
  241.     ' **********************************
  242.     ' * Compute reflected contribution *
  243.     ' **********************************
  244.     NdotV = nx * Vx + ny * Vy + nz * Vz
  245.     r_ref = 0
  246.     g_ref = 0
  247.     b_ref = 0
  248.     If IsReflective And depth > 1 Then
  249.         ' Find vector M in the direction of reflection.
  250.         mx = 2 * nx * NdotV - Vx
  251.         my = 2 * ny * NdotV - Vy
  252.         mz = 2 * nz * NdotV - Vz
  253.         
  254.         TraceRay depth - 1, HitX, HitY, HitZ, mx, my, mz, r1, g1, b1
  255.         r_ref = Krr * r1
  256.         g_ref = Krg * g1
  257.         b_ref = Krb * b1
  258.     End If
  259.     
  260.     ' **********************************
  261.     ' * Compute refracted contribution *
  262.     ' **********************************
  263.     r_trd = 0
  264.     g_trd = 0
  265.     b_trd = 0
  266.     r_tra = 0
  267.     g_tra = 0
  268.     b_tra = 0
  269.     If IsTransparent Then
  270.         ' Find the transmission vector T.
  271.         If NdotV > 0 Then
  272.             ' The ray is entering this object.
  273.             cos1 = NdotV
  274.         Else
  275.             ' The ray is exiting this object.
  276.             cos1 = -NdotV
  277.         End If
  278.         n_ratio = N1 / N2
  279.         cos2 = Sqr(1 - (1 - cos1 * cos1) * n_ratio * n_ratio)
  280.         cos_factor = cos2 - cos1 * n_ratio
  281.         tx = -Vx * n_ratio - cos_factor * nx
  282.         ty = -Vy * n_ratio - cos_factor * ny
  283.         tz = -Vz * n_ratio - cos_factor * nz
  284.             
  285.         ' If LdotV < 0, the viewpoint and light are on
  286.         ' opposite sides of the surface. In that case
  287.         ' there is direct transmitted light and no
  288.         ' specular reflection.
  289.         '
  290.         ' If LdotV > 0, the viewpoint and light are on
  291.         ' the same side of the surface. Then there
  292.         ' is specular reflection and no direct
  293.         ' transmitted light.
  294.         LdotV = lx * Vx + ly * Vy + lz * Vz
  295.         
  296.         ' Find the directly transmitted component.
  297.         If LdotV < 0 Then
  298.             NdotT = nx * tx + ny * ty + nz * tz
  299.             NdotT_Nt = NdotT ^ Nt
  300.             r_trd = Ktr * NdotT_Nt
  301.             g_trd = Ktg * NdotT_Nt
  302.             b_trd = Ktb * NdotT_Nt
  303.         End If
  304.         
  305.         ' Find the indirectly transmitted component.
  306.         If depth > 1 Then
  307.             TraceRay depth - 1, hit_x, hit_y, hit_z, tx, ty, tz, r1, g1, b1
  308.             r_tra = Ktr * r1
  309.             g_tra = Ktg * g1
  310.             b_tra = Ktb * b1
  311.         End If
  312.     End If
  313.     
  314.     ' See how intense to make the color.
  315.     ' Some of the reflections may be close to
  316.     ' the light source so these values can get big.
  317.     rlng = r_amb + _
  318.         LightIir / (l_len + LightKdist) * _
  319.             (r_dif + spec) + _
  320.         r_ref + r_tra + r_trd
  321.     glng = g_amb + _
  322.         LightIig / (l_len + LightKdist) * _
  323.             (g_dif + spec) + _
  324.         g_ref + g_tra + g_trd
  325.     blng = b_amb + _
  326.         LightIib / (l_len + LightKdist) * _
  327.             (b_dif + spec) + _
  328.         b_ref + b_tra + b_trd
  329.     If rlng > 255 Then rlng = 255
  330.     If glng > 255 Then glng = 255
  331.     If blng > 255 Then blng = 255
  332.     R = rlng
  333.     G = glng
  334.     B = blng
  335. End Sub
  336.  
  337. ' ************************************************
  338. ' Compute the distance from point (x3, y3, z3)
  339. ' along vector <wx, wy, wz> to the cylinder.
  340. '
  341. ' Save the point of intersection in
  342. ' (HitX, HitY, HitZ) for later use.
  343. ' ************************************************
  344. Public Function RayDistance(x3 As Single, y3 As Single, z3 As Single, Wx As Single, Wy As Single, Wz As Single) As Single
  345. Dim x1 As Single
  346. Dim y1 As Single
  347. Dim z1 As Single
  348. Dim Vx As Single
  349. Dim Vy As Single
  350. Dim Vz As Single
  351. Dim Vlen2 As Single
  352. Dim WdotV As Single
  353. Dim A As Single
  354. Dim B As Single
  355. Dim Cx As Single
  356. Dim Cy As Single
  357. Dim Cz As Single
  358. Dim dx As Single
  359. Dim dy As Single
  360. Dim dz As Single
  361. Dim A1 As Single
  362. Dim b1 As Single
  363. Dim C1 As Single
  364. Dim B24AC As Single
  365. Dim u1 As Single
  366. Dim u2 As Single
  367.  
  368.     ' Find the axis vector.
  369.     Vx = Point2.trans(1) - Point1.trans(1)
  370.     Vy = Point2.trans(2) - Point1.trans(2)
  371.     Vz = Point2.trans(3) - Point1.trans(3)
  372.     
  373.     ' Find A and B for t = A * u + B.
  374.     Vlen2 = Vx * Vx + Vy * Vy + Vz * Vz
  375.     WdotV = Wx * Vx + Wy * Vy + Wz * Vz
  376.     A = WdotV / Vlen2
  377.     
  378.     x1 = Point1.trans(1)
  379.     y1 = Point1.trans(2)
  380.     z1 = Point1.trans(3)
  381.     B = (Vx * (x3 - x1) + _
  382.          Vy * (y3 - y1) + _
  383.          Vz * (z3 - z1)) / Vlen2
  384.         
  385.     ' Solve for u.
  386.     Cx = Wx - Vx * A
  387.     Cy = Wy - Vy * A
  388.     Cz = Wz - Vz * A
  389.     dx = x3 - x1 - Vx * B
  390.     dy = y3 - y1 - Vy * B
  391.     dz = z3 - z1 - Vz * B
  392.     A1 = Cx * Cx + Cy * Cy + Cz * Cz
  393.     b1 = 2 * (Cx * dx + Cy * dy + Cz * dz)
  394.     C1 = dx * dx + dy * dy + dz * dz - Radius * Radius
  395.     ' Solve the quadratic A1*u^2 + B1*u + C1 = 0.
  396.     B24AC = b1 * b1 - 4 * A1 * C1
  397.     If B24AC < 0 Then
  398.         RayDistance = INFINITY
  399.         Exit Function
  400.     ElseIf B24AC = 0 Then
  401.         u1 = -b1 / 2 / A1
  402.     Else
  403.         B24AC = Sqr(B24AC)
  404.         u1 = (-b1 + B24AC) / 2 / A1
  405.         u2 = (-b1 - B24AC) / 2 / A1
  406.         ' Use only positive t values.
  407.         If u1 < 0.02 Then u1 = u2
  408.         If u2 < 0.02 Then u2 = u1
  409.         ' Use the smaller t value.
  410.         If u1 > u2 Then u1 = u2
  411.     End If
  412.     
  413.     ' If there is no positive u value, there's no
  414.     ' intersection in this direction.
  415.     If u1 < 0.02 Then
  416.         RayDistance = INFINITY
  417.         Exit Function
  418.     End If
  419.     
  420.     ' See where on the cylinder this is.
  421.     HitT = u1 * A + B
  422.     ' If this is not between Point1 and Point2,
  423.     ' ignore it.
  424.     If HitT < 0 Or HitT > 1 Then
  425.         RayDistance = INFINITY
  426.         Exit Function
  427.     End If
  428.     
  429.     ' Compute the actual hit location.
  430.     HitX = x3 + u1 * Wx
  431.     HitY = y3 + u1 * Wy
  432.     HitZ = z3 + u1 * Wz
  433.  
  434.     ' Compute the distance from (x3, y3, z3).
  435.     A1 = x3 - HitX
  436.     b1 = y3 - HitY
  437.     C1 = z3 - HitZ
  438.     RayDistance = Sqr(A1 * A1 + b1 * b1 + C1 * C1)
  439. End Function
  440.  
  441. ' ************************************************
  442. ' Initialize the data.
  443. ' ************************************************
  444. Public Sub Initialize(R As Single, p1x As Single, p1y As Single, p1z As Single, p2x As Single, p2y As Single, p2z As Single)
  445.     Radius = R
  446.     Point1.coord(1) = p1x
  447.     Point1.coord(2) = p1y
  448.     Point1.coord(3) = p1z
  449.     Point1.coord(4) = 1
  450.     Point2.coord(1) = p2x
  451.     Point2.coord(2) = p2y
  452.     Point2.coord(3) = p2z
  453.     Point2.coord(4) = 1
  454. End Sub
  455.  
  456.  
  457. ' ************************************************
  458. ' Set N and Ks for specular reflection.
  459. ' ************************************************
  460. Sub SetSpec(n As Single, s As Single)
  461.     SpecN = n
  462.     Ks = s
  463. End Sub
  464.  
  465. ' ************************************************
  466. ' Return the latest Hit location.
  467. ' ************************************************
  468. Public Sub HitLocation(x As Single, y As Single, z As Single)
  469.     x = HitX
  470.     y = HitY
  471.     z = HitZ
  472. End Sub
  473.  
  474. ' ************************************************
  475. ' Set constants for diffuse reflection.
  476. ' ************************************************
  477. Sub SetKd(R As Single, G As Single, B As Single)
  478.     Kdr = R
  479.     Kdg = G
  480.     Kdb = B
  481. End Sub
  482.  
  483. ' ************************************************
  484. ' Set constants for ambient light.
  485. ' ************************************************
  486. Sub SetKa(R As Single, G As Single, B As Single)
  487.     Kar = R
  488.     Kag = G
  489.     Kab = B
  490. End Sub
  491. ' ************************************************
  492. ' Set constants for reflected light.
  493. ' ************************************************
  494. Sub SetKr(R As Single, G As Single, B As Single)
  495.     Krr = R
  496.     Krg = G
  497.     Krb = B
  498.     IsReflective = (R > 0 Or G > 0 Or B > 0)
  499. End Sub
  500.  
  501.  
  502.